package com.boruan.shengtangfeng.core.service.impl;

import java.io.*;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.aliyun.oss.model.PutObjectResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.boruan.shengtangfeng.core.service.IOssService;
import com.boruan.shengtangfeng.core.utils.Consts;
import com.boruan.shengtangfeng.core.utils.GlobalReponse;
import com.boruan.shengtangfeng.core.utils.UUIDUtil;
import com.boruan.shengtangfeng.core.vo.OssCallbackResult;
import com.boruan.shengtangfeng.core.vo.OssPolicyResult;

/**
 * Created by macro on 2018/5/17.
 */
@Service
public class OssServiceImpl implements IOssService {

	private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class);
	@Value("${aliyun.oss.policy.expire}")
	private int ALIYUN_OSS_EXPIRE;
	@Value("${aliyun.oss.maxSize}")
	private int ALIYUN_OSS_MAX_SIZE;
	@Value("${aliyun.oss.callback}")
	private String ALIYUN_OSS_CALLBACK;
	@Value("${aliyun.oss.bucketName}")
	private String ALIYUN_OSS_BUCKET_NAME;
	@Value("${aliyun.oss.publicEndpoint}")
    private String PUBLIC_ALIYUN_OSS_ENDPOINT;
	@Value("${aliyun.oss.publicAction}")
	private String PUBLIC_ALIYUN_OSS_ACTION;
    @Value("${aliyun.oss.privateEndpoint}")
    private String PRIVATE_ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.dir.prefix}")
    private String ALIYUN_OSS_DIR_PREFIX;
    @Value("${aliyun.oss.accessKeyId}")
    private String ALIYUN_OSS_KEY;
    @Value("${aliyun.oss.accessKeySecret}")
    private String ALIYUN_OSS_SECRET;
    @Value("${aliyun.oss.tokenExpireTime}")
    private Long tokenExpireTime;
    @Value("${aliyun.oss.policyFileContent}")
    private String policyFileContent;

    
    @Value("${aliyun.oss.arn}")
    private String arn;
    
	@Resource(name="publicOssClient")
	private OSSClient publilcOssClient;
	@Resource(name="privateOssClient")
	private OSSClient privateOssClient;
	@Resource(name="acsClient")
	private DefaultAcsClient acsClient;

	/**
	 * 签名生成
	 */
	@Override
	public OssPolicyResult policy() {
		OssPolicyResult result = new OssPolicyResult();
		// 存储目录
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String dir = ALIYUN_OSS_DIR_PREFIX+sdf.format(new Date());
		// 签名有效期
		long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
		Date expiration = new Date(expireEndTime);
		// 文件大小
		long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024;
		// 回调
//		OssCallbackParam callback = new OssCallbackParam();
//		callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
//		callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
//		callback.setCallbackBodyType("application/x-www-form-urlencoded");
		// 提交节点
		try {
			PolicyConditions policyConds = new PolicyConditions();
			policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
			policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
			String postPolicy = publilcOssClient.generatePostPolicy(expiration, policyConds);
			byte[] binaryData = postPolicy.getBytes("utf-8");
			String policy = BinaryUtil.toBase64String(binaryData);
			String signature = publilcOssClient.calculatePostSignature(postPolicy);
//			String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes("utf-8"));
			// 返回结果
			result.setAccessKeyId(publilcOssClient.getCredentialsProvider().getCredentials().getAccessKeyId());
			result.setPolicy(policy);
			result.setSignature(signature);
			result.setDir(dir);
//			result.setCallback(callbackData);
			result.setHost(PUBLIC_ALIYUN_OSS_ACTION);
			//TODO限制视频上传大小
			result.setLimit(500);
		} catch (Exception e) {
			LOGGER.error("签名生成失败", e);
		}
		return result;
	}

	@Override
	public OssCallbackResult callback(HttpServletRequest request) {
		OssCallbackResult result= new OssCallbackResult();
		String filename = request.getParameter("filename");
		filename = "http://".concat(ALIYUN_OSS_BUCKET_NAME).concat(".").concat(PUBLIC_ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
		result.setFilename(filename);
		result.setSize(request.getParameter("size"));
		result.setMimeType(request.getParameter("mimeType"));
		result.setWidth(request.getParameter("width"));
		result.setHeight(request.getParameter("height"));
		return result;
	}
	
	/**
     * @Description: 上传文件
     * @date:2018年12月20日 上午9:13:24
     */
    @Override
    public GlobalReponse uploadFile(MultipartFile file) {

        String fileName = file.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);

        String dirName = "";

        if ("bmp,jpg,png,tif,gif,pcx,tga,exif,fpx,svg,psd,cdr,pcd,dxf,ufo,eps,ai,raw,WMF,webp".contains(suffix)) {
            dirName = "picture";
        } else {
            dirName = "video";
        }

        // 存储目录
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dir = ALIYUN_OSS_DIR_PREFIX.replaceFirst("videos",  dirName) + sdf.format(new Date());
        String newName = dir + "/"+UUIDUtil.getUUID()+"." + suffix;
        String url = "";
        try {
            // Endpoint以杭州为例，其它Region请按实际情况填写。
            // 云账号AccessKey有所有API访问权限，建议遵循阿里云安全最佳实践，创建并使用RAM子账号进行API访问或日常运维，请登录
            // 创建OSSClient实例。
            // 上传文件流。
            privateOssClient.putObject(ALIYUN_OSS_BUCKET_NAME, newName, file.getInputStream());
            url = PUBLIC_ALIYUN_OSS_ACTION +"/"+newName;
        }  catch (Exception e) {
            e.printStackTrace();
        }
        return GlobalReponse.success((Object)url);
    }

    @Override
    public GlobalReponse uploadFiles(MultipartFile[] files) {
        try {
            if (files.length == 0) {
                return GlobalReponse.fail("没有获取到文件");
            }
            StringBuilder sb = new StringBuilder();
            // 存储目录
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String dir = ALIYUN_OSS_DIR_PREFIX+sdf.format(new Date());
            for (MultipartFile file : files) {
                try {
                    String fileName = file.getOriginalFilename();
                    String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
                    String newName = dir + "/"+UUIDUtil.getUUID()+"." + suffix;
                    String url = "";
                    try {
                        // Endpoint以杭州为例，其它Region请按实际情况填写。
                        // 云账号AccessKey有所有API访问权限，建议遵循阿里云佳实践，创建并使用RAM子账号进行API访问或日常运维，请登录
                        // 创建OSSClient实例。
                        // 上传文件流。
                        privateOssClient.putObject(ALIYUN_OSS_BUCKET_NAME, newName, file.getInputStream());
                        url = PUBLIC_ALIYUN_OSS_ACTION +"/"+newName;
                    }  catch (Exception e) {
                        e.printStackTrace();
                    }
                    sb.append(url+",");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            String path = sb.toString();
            return GlobalReponse.success((Object)path.substring(0, path.length() - 1));
        } catch (Exception e) {
            e.printStackTrace();
            return GlobalReponse.fail("上传失败:"+e.getMessage());
        }
    }
    
 
    
    /**
     * 获取sts上传秘钥
     */
    @Override
    public Map<String, String> getSts(Long userId){
        
        // 只有 RAM用户（子账号）才能调用 AssumeRole 接口
        // 阿里云主账号的AccessKeys不能用于发起AssumeRole请求
        // 请首先在RAM控制台创建一个RAM用户，并为这个用户创建AccessKeys
        
        // RoleSessionName 是临时Token的会话名称，自己指定用于标识你的用户，主要用于审计，或者用于区分Token颁发给谁
        // 但是注意RoleSessionName的长度和规则，不要有空格，只能有'-' '_' 字母和数字等字符
        // 具体规则请参考API文档中的格式要求
        String roleSessionName = "alice-"+userId;

        // 此处必须为 HTTPS
        ProtocolType protocolType = ProtocolType.HTTPS;

        try {
            
         // 创建一个 AssumeRoleRequest 并设置请求参数
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setVersion(Consts.STS_API_VERSION);
            request.setMethod(MethodType.POST);
            request.setProtocol(protocolType);

            request.setRoleArn(arn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policyFileContent);
            request.setDurationSeconds(tokenExpireTime);
            // 发起请求，并得到response
            final AssumeRoleResponse stsResponse = acsClient.getAcsResponse(request);
            
            Map<String, String> respMap = new LinkedHashMap<String, String>();
            respMap.put("StatusCode", "200");
            respMap.put("AccessKeyId", stsResponse.getCredentials().getAccessKeyId());
            respMap.put("AccessKeySecret", stsResponse.getCredentials().getAccessKeySecret());
            respMap.put("SecurityToken", stsResponse.getCredentials().getSecurityToken());
            respMap.put("Expiration", stsResponse.getCredentials().getExpiration());
               
            return respMap;
            
        } catch (ClientException e) {
            Map<String, String> respMap = new LinkedHashMap<String, String>();
            respMap.put("StatusCode", "500");
            respMap.put("ErrorCode", e.getErrCode());
            respMap.put("ErrorMessage", e.getErrMsg());
            return respMap;
        }
        
    }
    /**
     * 读取配置文件
     * @param path
     * @return
     */
    public static String ReadJson(String path){
        //从给定位置获取文件

        URL url =  OssServiceImpl.class.getClassLoader().getResource(path);
        File file = new File(url.getFile());
        BufferedReader reader = null;
        //返回值,使用StringBuffer
        StringBuffer data = new StringBuffer();
        //
        try {
            reader = new BufferedReader(new FileReader(file));
            //每次读取文件的缓存
            String temp = null;
            while((temp = reader.readLine()) != null){
                data.append(temp);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭文件流
            if (reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return data.toString();
    }

    @Override
    public String uploadObject2OSS(File file) {
        long startTime = System.currentTimeMillis();
        String fileName = file.getName();
        String url = "";
        String image = "file/";
        String newName = image + fileName;
        try {
            OSSClient ossClient = new OSSClient(PUBLIC_ALIYUN_OSS_ENDPOINT, ALIYUN_OSS_KEY, ALIYUN_OSS_SECRET);

            //以输入流的形式上传文件
            InputStream is = new FileInputStream(file);

            PutObjectResult putResult = ossClient.putObject(ALIYUN_OSS_BUCKET_NAME, image + fileName, is);
            url = " https://public.stftt.com" + "/" + newName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("*********上传耗时 ***********: " + (endTime - startTime));
        return url;
    }
}
